package com.flow.framework.module.call.rpc.util;

import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.util.io.IoUtil;
import com.flow.framework.common.util.verify.VerifyUtil;
import feign.Response;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * feign工具类
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/2/19
 */
@Slf4j
public class FeignUtil {

    /**
     * 匹配响应字符的编码的正则表达式
     */
    private static final Pattern CHARSET_PATTERN = Pattern.compile("charset=([^\\s])");

    /**
     * 占位符开始字符串
     */
    private static final String PLACE_HOLDER_START = "${";

    /**
     * 占位符结束字符串
     */
    private static final String PLACE_HOLDER_END = "}";

    /**
     * 给定字符串中是否包含$符类型的占位符
     *
     * @param str 字符串
     * @return 是否包含$符类型的占位符
     */
    public static boolean isDollarPlaceHolder(String str) {
        if (VerifyUtil.isEmpty(str)) {
            return false;
        }
        int start = str.indexOf(PLACE_HOLDER_START);
        int end = str.lastIndexOf(PLACE_HOLDER_END);
        return start < end;
    }

    /**
     * 获取响应中的字符编码类型
     *
     * @param headers headers
     * @return 响应中的字符编码类型
     */
    public static Charset getResponseCharset(Map<String, Collection<String>> headers) {
        Charset defaultCharset = StandardCharsets.UTF_8;
        Collection<String> strings = headers.get("content-type");
        if (strings == null || strings.size() == 0) {
            return defaultCharset;
        }

        Matcher matcher = CHARSET_PATTERN.matcher(strings.iterator().next());
        if (!matcher.lookingAt()) {
            return defaultCharset;
        }

        String charset = matcher.group(1);
        if (!Charset.isSupported(charset)) {
            return defaultCharset;
        }
        return Charset.forName(charset);
    }

    /**
     * 获取响应限定长度的响应body的字节数据
     *
     * @param response    响应
     * @param limitLength 限定长度
     * @return 限定长度的响应body的字节数据
     */
    public static byte[] getResponseByteBody(Response response, int limitLength) {
        InputStream inputStream = null;
        try {
            inputStream = response.body().asInputStream();
            if (response.body() != null) {
                return IoUtil.toLimitByteArray(inputStream, limitLength);
            }
            return new byte[]{};
        } catch (IOException e) {
            log.error("read body error. url: {}", response.request().url(), e);
            throw new CheckedException(SystemErrorCode.REMOTE_PROCEDURE_CALL_ERROR);
        } finally {
            IoUtil.close(inputStream);
        }
    }
}
